package com.boot.security.server.filter;

import com.boot.security.server.dao.PermissionDao;
import com.boot.security.server.dto.LoginUser;
import com.boot.security.server.dto.Token;
import com.boot.security.server.model.Permission;
import com.boot.security.server.user.model.SysUsers;
import com.boot.security.server.service.TokenService;
import com.boot.security.server.user.service.UserService;
import com.boot.security.server.utils.ResponseUtil;
import com.boot.security.server.utils.UserUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;

/**
 * 单点登录过滤器方式实现
 * @author king
 */
public class SessionFilterSSOToken implements Filter {

    private static Logger logger = LoggerFactory.getLogger(SessionFilterSSOToken.class);
    @Autowired
    private TokenService tokenService;
    @Autowired
    private UserService userService;
    @Autowired
    private PermissionDao permissionDao;

    /**
     * session初始化
     */
    @Override
    public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest rq = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        String servletPath = rq.getRequestURI();
        HttpSession session = rq.getSession();
        String userId = null;// 用户登录名

        // 如果用户已登录，无需在登录直接跳转
        if (isLogin(rq)) {
            logger.info("用户已登陆！");
            chain.doFilter(request, response);
            return;
        }
        // 检查Cookie获得 SSO Token
        String token = checkCookie(rq);
        // 验证登录
        if (token != null) {
            //            userId = SSOTokenLogin(token);
            //            userId = SSOTokenLoginByByte(token);
            userId = SSOTokenLoginGetCode(token);
        }
        // SSO Token 没有登陆直接跳转
        if (userId == null) {
            chain.doFilter(request, response);
            return;
        } else {
            // TODO 做系统的登录操作
            SysUsers sysUser = userService.getUser(userId);
            if (sysUser == null) {
                throw new AuthenticationCredentialsNotFoundException("工号不存在");
            } else if (sysUser.getStatus() == SysUsers.Status.LOCKED) {
                throw new LockedException("工号被锁定,请联系管理员");
            } else if (sysUser.getStatus() == SysUsers.Status.DISABLED) {
                throw new DisabledException("工号已作废");
            }
            LoginUser loginUser = new LoginUser();
            BeanUtils.copyProperties(sysUser, loginUser);
            List<Permission> permissions = permissionDao.listByUserId(sysUser.getId());
            loginUser.setPermissions(permissions);
            Token token1 = tokenService.saveToken(loginUser);
            ResponseUtil.responseJson(resp, HttpStatus.OK.value(), token1);
        }
    }

    /**
     * 判断用户是否登录 根据应用自行调整
     * @param request
     * @return
     */
    private boolean isLogin (HttpServletRequest request) {
        boolean isLogin = false;
        LoginUser loginUser = UserUtil.getLoginUser();
        if (loginUser != null) {
            isLogin = true;
        }
        return isLogin;
    }

    /**
     * 检查Cookie获得 SSO Token
     * key=iPlanetDirectoryPro
     * @param request
     * @return token
     */
    private String checkCookie (HttpServletRequest request) {
        Cookie cookies[] = request.getCookies();
        String token = null;
        if (cookies != null) {
            for (int i = 0; i < cookies.length; i++) {
                if (cookies[i].getName().equals("iPlanetDirectoryPro")) {
                    token = cookies[i].getValue();
                    break;
                }
            }
        }
        return token;
    }

    /**
     * 根据SSO Token 获得用户ID  token = iPlanetDirectoryPro
     * @param token
     * @return
     */
    private String SSOTokenLogin (String token) {
        String userid = null;
        URLConnection uc = null;

        try {
            URL url = new URL("http://portal.oa.unionpay.com/ssotoken/checktoken");// token验证地址
            uc = url.openConnection();
            uc.setDoOutput(true);
            uc.setDoInput(true);
            uc.setUseCaches(false);

            ObjectOutputStream objectstream = new ObjectOutputStream(uc.getOutputStream());
            objectstream.writeObject(token);
            objectstream.flush();
            objectstream.close();

            InputStream in = uc.getInputStream();
            ObjectInputStream objectin = new ObjectInputStream(in);
            Object myobject = objectin.readObject();
            userid = (String) myobject;// 此处userid即LDAP中的用户名.
            objectin.close();
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return userid;
    }

    /**
     * 根据SSO Token 获得用户ID //iPlanetDirectoryPro
     * @param token
     * @return userid
     */
    private String SSOTokenLoginByByte (String token) {
        String userid = null;
        URLConnection uc = null;

        try {
            URL url = new URL("http://portal.oa.unionpay.com/ssotoken/checktokenbyte");
            uc = url.openConnection();

            uc.setDoOutput(true);
            uc.setDoInput(true);
            uc.setUseCaches(false);

            OutputStream objectout = uc.getOutputStream();
            objectout.write(token.getBytes());
            objectout.flush();
            objectout.close();

            InputStream in = uc.getInputStream();
            byte[] data = new byte[in.available()];
            in.read(data, 0, data.length);
            userid = new String(data, "Ascii");
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return userid;
    }

    /**
     * 根据SSO Token 获得用户工号
     * @param token
     * @return 工号
     */
    private String SSOTokenLoginGetCode (String token) {
        String userCode = null;
        URLConnection uc = null;
        try {
            URL url = new URL("http://portal.oa.unionpay.com/ssotoken/checktokencode");
            uc = url.openConnection();
            uc.setDoOutput(true);
            uc.setDoInput(true);
            uc.setUseCaches(false);

            ObjectOutputStream objectstream = new ObjectOutputStream(uc.getOutputStream());
            objectstream.writeObject(token);
            objectstream.flush();
            objectstream.close();

            InputStream in = uc.getInputStream();
            ObjectInputStream objectin = new ObjectInputStream(in);
            Object myobject = objectin.readObject();
            userCode = (String) myobject;
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return userCode;
    }

    @Override
    public void init (FilterConfig arg0) throws ServletException {}

    @Override
    public void destroy () {}
}
